package com.example.demo.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class MyServer4 {


    /**
     * 缓冲区扩容问题：该不该扩容，怎么扩容
     */

    // ByteBuffer接受的数据 \n
    private static void doLineSplit(ByteBuffer buffer) {
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            if (buffer.get(i) == '\n') {
                int length = i + 1 - buffer.position();
                ByteBuffer target = ByteBuffer.allocate(length);
                for (int j = 0; j < length; j++) {
                    target.put(buffer.get());
                }
                //截取工作完成
                target.flip();
                System.out.println("StandardCharsets.UTF_8.decode(target).toString() = " + StandardCharsets.UTF_8.decode(target).toString());
            }
        }
        buffer.compact();
    }

    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8000));
        serverSocketChannel.configureBlocking(false);//selector只有在非阻塞情况下才能使用
        //引入监管者
        Selector selector = Selector.open();
        //把serverSocketChannel 交给selector进行管理

        SelectionKey selectionKey = serverSocketChannel.register(selector, 0, null);
        //设置监管accept状态
        selectionKey.interestOps(SelectionKey.OP_ACCEPT);
        /*介绍下selector的属性
        keys        :注册列表
        selectorKeys:实际存在列表
        * */
        while (true) {
            //开始监控指定的状态，不再傻乎乎的空转了
            selector.select();
//            System.out.println("有动作");
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                if (key.isAcceptable()) {
                    //非阻塞处理新连接
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel sc = channel.accept();
                    sc.configureBlocking(false);
                    ByteBuffer allocate = ByteBuffer.allocate(2);
                    SelectionKey register = sc.register(selector, 0, allocate);
                    register.interestOps(SelectionKey.OP_WRITE);
                } else if (key.isWritable()) {
                    //非阻塞处理写请求
                    try {
                        SocketChannel sc = (SocketChannel) key.channel();
//                        ByteBuffer buffer = ByteBuffer.allocate(7);
                        ByteBuffer buffer = (ByteBuffer) key.attachment();
                        int read = sc.read(buffer);
                        if (read == -1 || read == 0) {
                            key.cancel();
                        } else {
                            doLineSplit(buffer);
                            //扩容
                            if (buffer.position() == buffer.limit()){
                                ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
                                buffer.flip();
                                newBuffer.put(buffer);
                                key.attach(newBuffer);
                            }
//                            buffer.flip();
//                            System.out.println("Charset.defaultCharset().decode(buffer).toString() = " + Charset.defaultCharset().decode(buffer).toString());
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        key.cancel();
                    }
                }
            }
        }
    }
}
